home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / pcxkit.zip / CLIP.DOC < prev    next >
Text File  |  1992-01-06  |  15KB  |  320 lines

  1. ===========================================================================
  2.  
  3.                                     CLIP
  4.  
  5.                              by Peter Donnelly
  6.                               1301 Ryan Street
  7.                                 Victoria BC
  8.                                Canada V8T 4Y8
  9.  
  10. ===========================================================================
  11.  
  12. INTRODUCTION
  13. ------------
  14.  
  15. The Borland Graphical Interface contains an easy-to-use procedure,
  16. PutImage, for displaying complex images on a portion of the screen.
  17. However, the Turbo C or Pascal programmer faces the difficulty of getting
  18. the image into memory in the first place - that is, of drawing it.
  19.  
  20. CLIP is a bridge between powerful commercial painting programs (such as
  21. Paintbrush and Deluxe Paint II Enhanced) and the BGI. It lets you "clip"
  22. images of any size (up to the 64K limit imposed by PutImage) from PCX files
  23. in EGA and VGA medium or high resolution, and puts these images in files
  24. that can be used in your C or Pascal routines with a minimum of effort.
  25.  
  26.  
  27. OPERATION
  28. ---------
  29.  
  30. The program is very simple to use. First create a screen-wide PCX graphics 
  31. file in 16-color 640x200, 640x350, or 640x480 resolution, using a painting 
  32. or screen-capture program. (If your software doesn't directly support the 
  33. PCX format, it may include a conversion program that does.) Then run CLIP 
  34. with the pathname of the graphics file on the command line; don't include 
  35. the ".PCX" part.
  36.  
  37. By default the program will come up in 640x480 resolution if your system
  38. supports it, but you can override this default by entering "/e" on the
  39. command line after the PCX file name, in which case the display mode will
  40. be 640x350 and only EGA palette information will be produced (more on this
  41. below).
  42.  
  43. Now, with the mouse, point to one corner of the image you wish to save.
  44. Hold down the left button and drag the mouse to create a frame around the
  45. image. The area you are defining includes the pixels covered by the frame
  46. lines, so that you can work right to the edge of the screen.
  47.  
  48. When you release the button, you are prompted to enter a name for the image
  49. file. Type the file name and press <Enter>, or abort with <Esc>. You may
  50. use any file name except one with the extension ".PAL".
  51.  
  52. If the image is too large for the BGI PutImage procedure, a bell sounds and
  53. you are not allowed to save. The size limit is about 58 percent of the
  54. screen in EGA mode or about 42 percent in VGA. If you want to save the
  55. entire screen, you can of course do so in chunks; but a better way is to
  56. use PCX.PAS to display the original PCX image.
  57.  
  58. By default the co-ordinates of the mouse are shown at the upper right
  59. corner of the screen. This information can be useful for cutting images
  60. exactly to size, especially if you have made a note of the desired
  61. boundaries while working in the magnified mode of your painting program.
  62. CLIP will ignore the display of co-ordinates when saving an image clipped
  63. from this part of the screen; however, you can toggle off the display with
  64. <F1> if you wish to see what lies beneath.
  65.  
  66. Continue saving images from the screen until you're done; then press
  67. <Alt-X> or <F10> to exit.
  68.  
  69.  
  70. USING CLIP IMAGES IN TURBO PASCAL AND TURBO C
  71. ---------------------------------------------
  72.  
  73. The data structure used by Borland's image-manipulating procedures and
  74. functions is the same in both Turbo Pascal and Turbo C, and CLIP's
  75. output files are equally usable with either language. The examples in this
  76. section will be in Pascal.
  77.  
  78. The disk file created by CLIP to store an image takes exactly the same
  79. form as the data structure created by the Turbo GetImage procedure and used
  80. by PutImage. It is an untyped file.
  81.  
  82. The first two words in the file store the width and height respectively of
  83. the image (counting from zero: an image of "1 by 1" is actually 2 by 2).
  84. The PutImage procedure uses these figures to set up the image properly, and
  85. they are also used by ImageSize to calculate the storage needed for the
  86. image. The BGI does not use data compression; a blank image occupies as
  87. much storage space as a complex image of the same dimensions.
  88.  
  89. Here is a simple routine to import an image from a file and display it at
  90. the current pointer.
  91.  
  92.   var    BitMap: Pointer;
  93.          f: file;
  94.  
  95.   Begin
  96.     Assign(f, 'MYIMAGE.IM');
  97.     Reset(f, 1);
  98.     GetMem(BitMap, FileSize(f));
  99.     BlockRead(f, BitMap^, FileSize(f));
  100.     PutImage(GetX, GetY, BitMap^, CopyPut);
  101.   End;
  102.  
  103. For a program that uses multiple images, it may be convenient to group all
  104. the images together in a single data file. It is easy to do so with the DOS
  105. Copy command. For example, to create a file "CHESSMEN" containing all the
  106. pieces:
  107.  
  108.   COPY KING/B + QUEEN + BISHOP + KNIGHT + ROOK + PAWN CHESSMEN
  109.  
  110. Note the "/B" argument after the first filename. Do not omit this; it is
  111. essential so that DOS treats all the files as binary and does not truncate
  112. any on encountering a Control-Z.
  113.  
  114. Obviously it is up to the programmer to ensure that the file-reading
  115. routines take into account the number of bytes occupied by each image. If
  116. the file contains images of different sizes that are to be stored
  117. dynamically as they are imported, you can use the ImageSize function to
  118. determine how much memory to allocate for each image:
  119.  
  120.   var   Width, Height, Size: word;
  121.         BitMap: pointer;
  122.         f: file;
  123.  
  124.   Begin
  125.     Assign(f, 'IMAGES.DTA');
  126.     Reset(f, 1);
  127.     Repeat
  128.       BlockRead(f, Width, 2);               { Get dimensions from header }
  129.       BlockRead(f, Height, 2);
  130.       Size:= ImageSize(0, 0, Width, Height);
  131.       GetMem(BitMap, Size);
  132.       Seek(f, FilePos(f) - 4);              { Back up }
  133.       BlockRead(f, Bitmap^, Size);          { Get whole image }
  134.     Until Eof(f);
  135.   End;    
  136.  
  137. This routine has the great advantage that you can alter the size of any of
  138. the component images in the file without having to change program code.
  139.  
  140.  
  141. INCORPORATING PALETTE CHANGES
  142. -----------------------------
  143.  
  144. Whenever you save an image file, CLIP automatically creates a palette
  145. file with the same name and the extension ".PAL". If CLIP is running in
  146. EGA (350-line) mode, this is simply an untyped 17-byte file containing a
  147. PaletteType record. For the VGA, it is an array of the RGB values for each
  148. of the 16 palette entries, or 48 bytes in all.
  149.  
  150. If you are working in 350-line mode on the VGA, the program presumes that
  151. you want only EGA palette data. If you want the full VGA information, you
  152. can load the file in 480-line mode; the resulting distortion will make no
  153. difference if the clipped images are ultimately to be displayed in their
  154. original 350-line format.
  155.  
  156. For the EGA, you can easily import saved palette values into your own
  157. program by BlockReading the palette file into a PaletteType variable. It is
  158. then simply a matter of passing that variable into SetAllPalette. (Of
  159. course, in many cases it may be preferable to hard-code the palette values,
  160. which can be examined with DEBUG.)
  161.  
  162. For the VGA, things are a bit more complicated. Here you have to make these
  163. declarations:
  164.  
  165.    type    RGBrec = record
  166.                       redval, greenval, blueval: byte;
  167.                     end;
  168.  
  169.    var     RGBpalette: array[0..15] of RGBrec;
  170.  
  171. Now BlockRead the palette file into RGBpalette. From here the data can be
  172. passed into Turbo's SetRGBPalette procedure; but first you have to make
  173. sure that the palette entries are pointing to the registers you are
  174. modifying. (In the VGA, the 16 palette entries don't contain color values;
  175. they contain the numbers of color registers, which in turn hold the actual
  176. colors.) By default the palette points to registers 0-5, 20, 7, and 56-63,
  177. which contain the standard EGA colors. You can either modify these
  178. registers or else use SetPalette to put the numbers 0-15 in the palette,
  179. then modify registers 0-15 with SetRGBPalette.
  180.  
  181. Files of 640x200 resolution are a special case. If you want to display
  182. images in the BGI "EGALo" format, only the 16 default colors are available,
  183. so it is unlikely you will want any palette information; in any case, the
  184. .PAL file produced by CLIP in its EGA mode will be of no use since the
  185. palette system is completely different in 200-line and 350-line modes. If
  186. you want the full VGA palette data for "VGALo" format, you must create the
  187. image in CLIP's 480-line mode. Again, the distortion will make no
  188. difference in the final product.
  189.  
  190.  
  191. LINKING DATA INTO THE .EXE FILE
  192. -------------------------------
  193.  
  194. For the sake of tidiness you may want to incorporate image and palette data
  195. in the executable file itself rather than keeping it in separate files.
  196. Turbo Pascal makes this easy.
  197.  
  198. Suppose you have an image of an apple in the file MYAPPLE.IM. First convert
  199. this to an object file with Borland's BINOBJ program (distributed with
  200. Turbo Pascal) thus:
  201.  
  202.   BINOBJ MYAPPLE.IM APPLE GETAPPLE
  203.  
  204. There are three arguments on the command line. The first is the source
  205. file, the second is the destination file (.OBJ is assumed), and the third
  206. is the public declaration or interface of the object file. You are creating
  207. APPLE.OBJ, which contains the public declaration GetApple.
  208.  
  209. Now, in your Pascal program, you declare a dummy "procedure" using the
  210. public name of the data, and link in the object file:
  211.  
  212.   procedure GetApple; external;
  213.   {$L APPLE.OBJ}
  214.  
  215. Finally, you declare a pointer variable and assign it the address of the
  216. dummy procedure:
  217.  
  218.   var   AppleImage: pointer;
  219.  
  220.   AppleImage:= @GetApple;
  221.  
  222. And when you want to display the image:
  223.  
  224.   PutImage(X, Y, AppleImage^, CopyPut);
  225.   
  226. X and Y are the desired screen coordinates for the upper left corner of the 
  227. image.
  228.  
  229. Although linked data is convenient, remember that it takes up memory space
  230. for the life of the program, whereas data from files can be read into
  231. dynamic memory and discarded when no longer needed. If memory is in short
  232. supply and an image only has to be written to the screen once (for example, 
  233. as part of a "title page"), a separate data file is probably the best 
  234. choice.
  235.  
  236.  
  237. A FEW WORDS ABOUT ANIMATION
  238. ---------------------------
  239.  
  240. As you will see from the enclosed HOEDOWN demonstration, simple animated
  241. effects are very easy to achieve. The demo uses just two repeating images 
  242. to give the illusion of movement, but you can use as many as you like, 
  243. writing them alternately to the two video pages.
  244.  
  245. If you look closely at the dancer, you will notice that some of the colors
  246. in his costume change as he moves across various parts of the backdrop. To
  247. understand why, and how to avoid this problem, you need to understand the
  248. concept of logical operations on pixel values.
  249.  
  250. Each of the palette entries may be represented by a pattern of four bits,
  251. as in the following table.
  252.  
  253.                 Entry  Bit Pattern  Default Color     
  254.                                                   
  255.                   0      0 0 0 0      black           
  256.                   1      0 0 0 1      blue            
  257.                   2      0 0 1 0      green           
  258.                   3      0 0 1 1      cyan            
  259.                   4      0 1 0 0      red             
  260.                   5      0 1 0 1      magenta         
  261.                   6      0 1 1 0      brown           
  262.                   7      0 1 1 1      lightgray       
  263.                   8      1 0 0 0      darkgray        
  264.                   9      1 0 0 1      lightblue       
  265.                  10      1 0 1 0      lightgreen      
  266.                  11      1 0 1 1      lightcyan       
  267.                  12      1 1 0 0      lightred        
  268.                  13      1 1 0 1      lightmagenta    
  269.                  14      1 1 1 0      yellow          
  270.                  15      1 1 1 1      white           
  271.                        
  272. There are five different ways that PutImage can write a pixel to the
  273. screen, three of which are most likely to be of use to the animator:
  274. CopyPut, OrPut, and XorPut.
  275.                        
  276. In the first of these, CopyPut, the procedure simply copies the new color
  277. over top of the old one, regardless of the value of either.
  278.                        
  279. HOEDOWN does not use CopyPut because if it did, the background color around
  280. the dancing figure would overwrite the scenic backdrop. (Try it and see.)
  281. Since we do not want the figure to be dancing inside a blank rectangle,
  282. instead we use the OrPut operator. This operator says to PutImage: "For
  283. each pixel, set all bits 'on' that are 'on' in either the new color or the
  284. old color." For example, using the default palette, if you put a blue pixel
  285. on top of a green one, the result will be cyan.
  286.                        
  287. Because the background color, whatever it is, is always taken from entry 0
  288. of the palette, it will never alter the color of a pixel where it is
  289. printed - it has no bits set, so the product of an OR operation with any
  290. other number will be that number (6 OR 0 = 6).
  291.  
  292. On the other hand, white (or whatever absolute color is in palette entry
  293. 15) will always be unchanged by an OR operation, since no more bits can be
  294. set by the operation. In the demo, the figure's blue jeans are drawn from
  295. palette entry 15, so they can safely pass in front of any other color.
  296.  
  297. Obviously if you wish to use the OrPut operator in PutImage you have to do
  298. some planning. Certain palette entries can be used safely on top of certain
  299. others; other combinations will lead to unwelcome changes. For instance, a
  300. glance at the table above shows that in the default palette, yellow can
  301. safely be superimposed on lightgreen but not on lightblue.
  302.  
  303. Another approach to the problems inherent in the use of OrPut is to create
  304. a "hole" in the backdrop before placing the image there. To create such a
  305. hole, you could draw a copy of the image in which all "background" pixels
  306. were white and all others black, then put this image on the screen with
  307. AndPut, which would leave the backdrop unaltered where the foreground image 
  308. was white and erase it elsewhere. The original image could then be OrPut 
  309. into this hole with no danger of color changes.
  310.  
  311. The other logical operator you may find yourself using is XorPut. XORing an
  312. image onto a blank background has the same effect as ORing it. If you
  313. XOR an image onto itself, the image is erased, leaving nothing but
  314. background color. (All bits that the old and new pixels have in common are
  315. set to 0.) This technique is not used in the demo, since we wish to restore
  316. the backdrop scenery, and this is done by copying it over the old dancing
  317. figure.
  318.  
  319. ===========================================================================
  320.